1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2013-07-20 Bernard first version 9 */ 10 11 #include <rtthread.h> 12 #include <rthw.h> 13 #include <board.h> 14 15 #include "armv7.h" 16 17 #ifdef RT_USING_VMM 18 #include <vmm_context.h> 19 #endif 20 21 #include "gic.h" 22 23 extern struct rt_thread *rt_current_thread; 24 #ifdef RT_USING_FINSH 25 extern long list_thread(void); 26 #endif 27 28 /** 29 * this function will show registers of CPU 30 * 31 * @param regs the registers point 32 */ 33 void rt_hw_show_register(struct rt_hw_exp_stack *regs) 34 { 35 rt_kprintf("Execption:\n"); 36 rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); 37 rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); 38 rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); 39 rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); 40 rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); 41 rt_kprintf("cpsr:0x%08x\n", regs->cpsr); 42 } 43 44 /** 45 * When comes across an instruction which it cannot handle, 46 * it takes the undefined instruction trap. 47 * 48 * @param regs system registers 49 * 50 * @note never invoke this function in application 51 */ 52 void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) 53 { 54 rt_kprintf("undefined instruction:\n"); 55 rt_hw_show_register(regs); 56 #ifdef RT_USING_FINSH 57 list_thread(); 58 #endif 59 rt_hw_cpu_shutdown(); 60 } 61 62 /** 63 * The software interrupt instruction (SWI) is used for entering 64 * Supervisor mode, usually to request a particular supervisor 65 * function. 66 * 67 * @param regs system registers 68 * 69 * @note never invoke this function in application 70 */ 71 void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) 72 { 73 rt_kprintf("software interrupt:\n"); 74 rt_hw_show_register(regs); 75 #ifdef RT_USING_FINSH 76 list_thread(); 77 #endif 78 rt_hw_cpu_shutdown(); 79 } 80 81 /** 82 * An abort indicates that the current memory access cannot be completed, 83 * which occurs during an instruction prefetch. 84 * 85 * @param regs system registers 86 * 87 * @note never invoke this function in application 88 */ 89 void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) 90 { 91 rt_kprintf("prefetch abort:\n"); 92 rt_hw_show_register(regs); 93 #ifdef RT_USING_FINSH 94 list_thread(); 95 #endif 96 rt_hw_cpu_shutdown(); 97 } 98 99 /** 100 * An abort indicates that the current memory access cannot be completed, 101 * which occurs during a data access. 102 * 103 * @param regs system registers 104 * 105 * @note never invoke this function in application 106 */ 107 void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) 108 { 109 rt_kprintf("data abort:"); 110 rt_hw_show_register(regs); 111 #ifdef RT_USING_FINSH 112 list_thread(); 113 #endif 114 rt_hw_cpu_shutdown(); 115 } 116 117 /** 118 * Normally, system will never reach here 119 * 120 * @param regs system registers 121 * 122 * @note never invoke this function in application 123 */ 124 void rt_hw_trap_resv(struct rt_hw_exp_stack *regs) 125 { 126 rt_kprintf("reserved trap:\n"); 127 rt_hw_show_register(regs); 128 #ifdef RT_USING_FINSH 129 list_thread(); 130 #endif 131 rt_hw_cpu_shutdown(); 132 } 133 134 #define GIC_ACK_INTID_MASK 0x000003ff 135 136 void rt_hw_trap_irq(void) 137 { 138 void *param; 139 unsigned long ir; 140 unsigned long fullir; 141 rt_isr_handler_t isr_func; 142 extern struct rt_irq_desc isr_table[]; 143 144 fullir = arm_gic_get_active_irq(0); 145 ir = fullir & GIC_ACK_INTID_MASK; 146 147 if (ir == 1023) 148 { 149 /* Spurious interrupt */ 150 return; 151 } 152 153 /* get interrupt service routine */ 154 isr_func = isr_table[ir].handler; 155 #ifdef RT_USING_INTERRUPT_INFO 156 isr_table[ir].counter++; 157 #endif 158 if (isr_func) 159 { 160 /* Interrupt for myself. */ 161 param = isr_table[ir].param; 162 /* turn to interrupt service routine */ 163 isr_func(ir, param); 164 } 165 #ifdef RT_USING_VMM 166 else 167 { 168 /* We have to EOI before masking the interrupts */ 169 arm_gic_ack(0, fullir); 170 vmm_virq_pending(ir); 171 return; 172 } 173 #endif 174 175 /* end of interrupt */ 176 arm_gic_ack(0, fullir); 177 } 178 179 void rt_hw_trap_fiq(void) 180 { 181 void *param; 182 unsigned long ir; 183 unsigned long fullir; 184 rt_isr_handler_t isr_func; 185 extern struct rt_irq_desc isr_table[]; 186 187 fullir = arm_gic_get_active_irq(0); 188 ir = fullir & GIC_ACK_INTID_MASK; 189 190 /* get interrupt service routine */ 191 isr_func = isr_table[ir].handler; 192 param = isr_table[ir].param; 193 194 /* turn to interrupt service routine */ 195 isr_func(ir, param); 196 197 /* end of interrupt */ 198 arm_gic_ack(0, fullir); 199 } 200 201