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 * 2011-01-13 weety modified from mini2440 9 * 2015-04-15 ArdaFu Split from AT91SAM9260 BSP 10 */ 11 12 #include <rtthread.h> 13 #include <rthw.h> 14 15 #define INT_IRQ 0x00 16 #define INT_FIQ 0x01 17 18 extern struct rt_thread *rt_current_thread; 19 #ifdef RT_USING_FINSH 20 extern long list_thread(void); 21 #endif 22 23 struct rt_hw_register 24 { 25 rt_uint32_t r0; 26 rt_uint32_t r1; 27 rt_uint32_t r2; 28 rt_uint32_t r3; 29 rt_uint32_t r4; 30 rt_uint32_t r5; 31 rt_uint32_t r6; 32 rt_uint32_t r7; 33 rt_uint32_t r8; 34 rt_uint32_t r9; 35 rt_uint32_t r10; 36 rt_uint32_t fp; 37 rt_uint32_t ip; 38 rt_uint32_t sp; 39 rt_uint32_t lr; 40 rt_uint32_t pc; 41 rt_uint32_t cpsr; 42 rt_uint32_t ORIG_r0; 43 }; 44 45 /** 46 * this function will show registers of CPU 47 * 48 * @param regs the registers point 49 */ 50 51 void rt_hw_show_register (struct rt_hw_register *regs) 52 { 53 rt_kprintf("Execption:\n"); 54 rt_kprintf("r00:0x%08x r01:0x%08x r02:0x%08x r03:0x%08x\n", 55 regs->r0, regs->r1, regs->r2, regs->r3); 56 rt_kprintf("r04:0x%08x r05:0x%08x r06:0x%08x r07:0x%08x\n", 57 regs->r4, regs->r5, regs->r6, regs->r7); 58 rt_kprintf("r08:0x%08x r09:0x%08x r10:0x%08x\n", 59 regs->r8, regs->r9, regs->r10); 60 rt_kprintf("fp :0x%08x ip :0x%08x\n", 61 regs->fp, regs->ip); 62 rt_kprintf("sp :0x%08x lr :0x%08x pc :0x%08x\n", 63 regs->sp, regs->lr, regs->pc); 64 rt_kprintf("cpsr:0x%08x\n", regs->cpsr); 65 } 66 67 /** 68 * When ARM7TDMI comes across an instruction which it cannot handle, 69 * it takes the undefined instruction trap. 70 * 71 * @param regs system registers 72 * 73 * @note never invoke this function in application 74 */ 75 void rt_hw_trap_udef(struct rt_hw_register *regs) 76 { 77 rt_hw_show_register(regs); 78 79 rt_kprintf("undefined instruction\n"); 80 rt_kprintf("thread - %s stack:\n", rt_current_thread->name); 81 82 #ifdef RT_USING_FINSH 83 list_thread(); 84 #endif 85 rt_hw_cpu_shutdown(); 86 } 87 88 /** 89 * The software interrupt instruction (SWI) is used for entering 90 * Supervisor mode, usually to request a particular supervisor 91 * function. 92 * 93 * @param regs system registers 94 * 95 * @note never invoke this function in application 96 */ 97 void rt_hw_trap_swi(struct rt_hw_register *regs) 98 { 99 rt_hw_show_register(regs); 100 101 rt_kprintf("software interrupt\n"); 102 rt_hw_cpu_shutdown(); 103 } 104 105 /** 106 * An abort indicates that the current memory access cannot be completed, 107 * which occurs during an instruction prefetch. 108 * 109 * @param regs system registers 110 * 111 * @note never invoke this function in application 112 */ 113 void rt_hw_trap_pabt(struct rt_hw_register *regs) 114 { 115 rt_hw_show_register(regs); 116 117 rt_kprintf("prefetch abort\n"); 118 rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name); 119 120 #ifdef RT_USING_FINSH 121 list_thread(); 122 #endif 123 rt_hw_cpu_shutdown(); 124 } 125 126 /** 127 * An abort indicates that the current memory access cannot be completed, 128 * which occurs during a data access. 129 * 130 * @param regs system registers 131 * 132 * @note never invoke this function in application 133 */ 134 void rt_hw_trap_dabt(struct rt_hw_register *regs) 135 { 136 rt_hw_show_register(regs); 137 138 rt_kprintf("data abort\n"); 139 rt_kprintf("thread - %s stack:\n", RT_NAME_MAX, rt_current_thread->name); 140 141 #ifdef RT_USING_FINSH 142 list_thread(); 143 #endif 144 rt_hw_cpu_shutdown(); 145 } 146 147 /** 148 * Normally, system will never reach here 149 * 150 * @param regs system registers 151 * 152 * @note never invoke this function in application 153 */ 154 void rt_hw_trap_resv(struct rt_hw_register *regs) 155 { 156 rt_kprintf("not used\n"); 157 rt_hw_show_register(regs); 158 rt_hw_cpu_shutdown(); 159 } 160 161 extern struct rt_irq_desc irq_desc[]; 162 extern rt_uint32_t rt_hw_interrupt_get_active(rt_uint32_t fiq_irq); 163 extern void rt_hw_interrupt_ack(rt_uint32_t fiq_irq, rt_uint32_t id); 164 165 void rt_hw_trap_irq() 166 { 167 rt_isr_handler_t isr_func; 168 rt_uint32_t irq; 169 void *param; 170 171 /* get irq number */ 172 irq = rt_hw_interrupt_get_active(INT_IRQ); 173 174 /* get interrupt service routine */ 175 isr_func = irq_desc[irq].handler; 176 param = irq_desc[irq].param; 177 178 /* turn to interrupt service routine */ 179 isr_func(irq, param); 180 181 rt_hw_interrupt_ack(INT_IRQ, irq); 182 #ifdef RT_USING_INTERRUPT_INFO 183 irq_desc[irq].counter ++; 184 #endif 185 } 186 187 void rt_hw_trap_fiq() 188 { 189 rt_isr_handler_t isr_func; 190 rt_uint32_t irq; 191 void *param; 192 193 /* get irq number */ 194 irq = rt_hw_interrupt_get_active(INT_FIQ); 195 196 /* get interrupt service routine */ 197 isr_func = irq_desc[irq].handler; 198 param = irq_desc[irq].param; 199 200 /* turn to interrupt service routine */ 201 isr_func(irq, param); 202 203 rt_hw_interrupt_ack(INT_FIQ, irq); 204 #ifdef RT_USING_INTERRUPT_INFO 205 irq_desc[irq].counter ++; 206 #endif 207 } 208