xref: /nrf52832-nimble/rt-thread/libcpu/arm/arm926/trap.c (revision 104654410c56c573564690304ae786df310c91fc)
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 
rt_hw_show_register(struct rt_hw_register * regs)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  */
rt_hw_trap_udef(struct rt_hw_register * regs)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  */
rt_hw_trap_swi(struct rt_hw_register * regs)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  */
rt_hw_trap_pabt(struct rt_hw_register * regs)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  */
rt_hw_trap_dabt(struct rt_hw_register * regs)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  */
rt_hw_trap_resv(struct rt_hw_register * regs)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 
rt_hw_trap_irq()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 
rt_hw_trap_fiq()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