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 #include "gic.h" 18 19 extern struct rt_thread *rt_current_thread; 20 #ifdef RT_USING_FINSH 21 extern long list_thread(void); 22 #endif 23 24 /** 25 * this function will show registers of CPU 26 * 27 * @param regs the registers point 28 */ 29 void rt_hw_show_register(struct rt_hw_exp_stack *regs) 30 { 31 rt_kprintf("Execption:\n"); 32 rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", regs->r0, regs->r1, regs->r2, regs->r3); 33 rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", regs->r4, regs->r5, regs->r6, regs->r7); 34 rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", regs->r8, regs->r9, regs->r10); 35 rt_kprintf("fp :0x%08x ip :0x%08x\n", regs->fp, regs->ip); 36 rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", regs->sp, regs->lr, regs->pc); 37 rt_kprintf("cpsr:0x%08x\n", regs->cpsr); 38 } 39 40 /** 41 * When comes across an instruction which it cannot handle, 42 * it takes the undefined instruction trap. 43 * 44 * @param regs system registers 45 * 46 * @note never invoke this function in application 47 */ 48 void rt_hw_trap_undef(struct rt_hw_exp_stack *regs) 49 { 50 rt_kprintf("undefined instruction:\n"); 51 rt_hw_show_register(regs); 52 #ifdef RT_USING_FINSH 53 list_thread(); 54 #endif 55 rt_hw_cpu_shutdown(); 56 } 57 58 /** 59 * The software interrupt instruction (SWI) is used for entering 60 * Supervisor mode, usually to request a particular supervisor 61 * function. 62 * 63 * @param regs system registers 64 * 65 * @note never invoke this function in application 66 */ 67 void rt_hw_trap_swi(struct rt_hw_exp_stack *regs) 68 { 69 rt_kprintf("software interrupt:\n"); 70 rt_hw_show_register(regs); 71 #ifdef RT_USING_FINSH 72 list_thread(); 73 #endif 74 rt_hw_cpu_shutdown(); 75 } 76 77 /** 78 * An abort indicates that the current memory access cannot be completed, 79 * which occurs during an instruction prefetch. 80 * 81 * @param regs system registers 82 * 83 * @note never invoke this function in application 84 */ 85 void rt_hw_trap_pabt(struct rt_hw_exp_stack *regs) 86 { 87 rt_kprintf("prefetch abort:\n"); 88 rt_hw_show_register(regs); 89 #ifdef RT_USING_FINSH 90 list_thread(); 91 #endif 92 rt_hw_cpu_shutdown(); 93 } 94 95 /** 96 * An abort indicates that the current memory access cannot be completed, 97 * which occurs during a data access. 98 * 99 * @param regs system registers 100 * 101 * @note never invoke this function in application 102 */ 103 void rt_hw_trap_dabt(struct rt_hw_exp_stack *regs) 104 { 105 rt_kprintf("data abort:"); 106 rt_hw_show_register(regs); 107 #ifdef RT_USING_FINSH 108 list_thread(); 109 #endif 110 rt_hw_cpu_shutdown(); 111 } 112 113 /** 114 * Normally, system will never reach here 115 * 116 * @param regs system registers 117 * 118 * @note never invoke this function in application 119 */ 120 void rt_hw_trap_resv(struct rt_hw_exp_stack *regs) 121 { 122 rt_kprintf("reserved trap:\n"); 123 rt_hw_show_register(regs); 124 #ifdef RT_USING_FINSH 125 list_thread(); 126 #endif 127 rt_hw_cpu_shutdown(); 128 } 129 130 void rt_hw_trap_irq(void) 131 { 132 void *param; 133 rt_isr_handler_t isr_func; 134 extern struct rt_irq_desc isr_table[]; 135 136 // vectNum = RESERVED[31:13] | CPUID[12:10] | INTERRUPT_ID[9:0] 137 // send ack and get ID source 138 uint32_t vectNum = gic_read_irq_ack(); 139 140 // Check that INT_ID isn't 1023 or 1022 (spurious interrupt) 141 if (vectNum & 0x0200) 142 { 143 gic_write_end_of_irq(vectNum); // send end of irq 144 } 145 else 146 { 147 // copy the local value to the global image of CPUID 148 unsigned cpu = (vectNum >> 10) & 0x7; 149 unsigned irq = vectNum & 0x1FF; 150 151 /* skip warning */ 152 cpu = cpu; 153 154 // Call the service routine stored in the handlers array. If there isn't 155 // one for this IRQ, then call the default handler. 156 /* get interrupt service routine */ 157 isr_func = isr_table[irq].handler; 158 #ifdef RT_USING_INTERRUPT_INFO 159 isr_table[irq].counter++; 160 #endif 161 if (isr_func) 162 { 163 /* Interrupt for myself. */ 164 param = isr_table[irq].param; 165 /* turn to interrupt service routine */ 166 isr_func(irq, param); 167 } 168 169 // Signal the end of the irq. 170 gic_write_end_of_irq(vectNum); 171 } 172 } 173 174 void rt_hw_trap_fiq(void) 175 { 176 /* TODO */ 177 } 178